/*	
 *	This file is part of eduDES.
 *
 *	Copyright 2009 Michael Morckos <mikey.morckos@gmail.com>
 *
 *	eduDES is free software: you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License as published by
 *	the Free Software Foundation, either version 3 of the License, or
 *	(at your option) any later version.
 *
 *	eduDES is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU General Public License for more details.
 *
 *	You should have received a copy of the GNU General Public License
 *	along with eduDES.  If not, see <http://www.gnu.org/licenses/>.
 */
 
#include "key.h"

unsigned char PC_1[56] = {57, 49, 41, 33, 25, 17, 9, 
						  1, 58, 50, 42, 34, 26, 18, 
						  10, 2, 59, 51, 43, 35, 27, 
						  19, 11, 3, 60, 52, 44, 36, 
						  63, 55, 47, 39, 31, 23, 15, 
						  7, 62, 54, 46, 38, 30, 22, 
						  14, 6, 61, 53, 45, 37, 29, 
						  21, 13, 5, 28, 20, 12, 4};
	
unsigned char PC_2[48] = {14, 17, 11, 24, 1, 5, 3, 28,
						  15, 6, 21, 10, 23, 19, 12, 4,
						  26, 8, 16, 7, 27, 20, 13, 2,
						  41, 52, 31, 37, 47, 55, 30, 40,
						  51, 45, 33, 48, 44, 49, 39, 56,
						  34, 53, 46, 42, 50, 36, 29, 32};

void init_key_en(unsigned char* input) {
 	orig_key = malloc(sizeof(unsigned char) * 64);
	curr_key = malloc(sizeof(unsigned char) * 56);
	C_key = malloc(sizeof(unsigned char) * 28);
	D_key = malloc(sizeof(unsigned char) * 28);
	final_key = malloc(sizeof(unsigned char) * 48);
	short i;
	for(i = 0; i < 64; i++) {
		if(((i + 1) % 8) == 0)
			orig_key[i] = -1;
		else
			orig_key[i] = input[i];	
	}
	applyPC_1();
	free(orig_key);
	orig_key = 0;		
}

void init_key_de(unsigned char* input) {
	if(!final_key)
		final_key = malloc(sizeof(unsigned char) * 48);
	short i;
	for(i = 0; i < 56; i++)
		final_key[i] = input[i];	
}

void applyPC_1() {
	short i;
	for(i = 0; i < 56; i++)
		curr_key[i] = orig_key[PC_1[i] - 1];
}

void splitkey() {
	short i;
	for(i = 0; i < 28; i++) {
		C_key[i] = curr_key[i];
		D_key[i] = curr_key[i + 28];
	}
}

void shiftkey(short factor) {
	unsigned char *tmp1 = malloc(sizeof(unsigned char) * 28),
				  *tmp2 = malloc(sizeof(unsigned char) * 28);
	short i, j;
	for(i = 0; i < factor; i++) {
		tmp1[28 - (factor - i)] = C_key[i];
		tmp2[28 - (factor - i)] = D_key[i];
	}				  
	for(i = factor, j = 0; i < 28; i++, j++) {
		tmp1[j] = C_key[i];
		tmp2[j] = D_key[i];
	}	
	for(i = 0; i < 28; i++) {
		C_key[i] = tmp1[i];
		D_key[i] = tmp2[i];
	}
	free(tmp1);
	free(tmp2);
	tmp1 = 0;
	tmp2 = 0;			  
}

void mergekey() {
	short i;
	for(i = 0; i < 28; i++) {
		curr_key[i] = C_key[i];
		curr_key[i + 28] = D_key[i];
	}
}

void applyPC_2() {
	short i;
	for(i = 0; i < 48; i++)	
		final_key[i] = curr_key[PC_2[i] - 1];
}

void closekey() {
	if(curr_key) {
		free(curr_key);
		curr_key = 0;
	}
	if(C_key) {
		free(C_key);
		C_key = 0;
	}
	if(D_key) {	
		free(D_key);
		D_key = 0;
	}
	if(final_key) {
		free(final_key);
		final_key = 0;
	}	
}
	 	
